package com.changgou.oauth.service.impl;

import com.changgou.oauth.service.AuthService;
import com.changgou.oauth.util.AuthToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${auth.ttl}")
    private long ttl;


    @Override
    public AuthToken login(String username, String password, String clientId, String clientSecret) {
//        //获取请求url
//        ServiceInstance serviceInstance = loadBalancerClient.choose("user-auth");
//        //http://localhost:9200
//        URI uri = serviceInstance.getUri();
//        String url = uri + "/oauth/token";
//
//        //封装实体参数和请求头
//        MultiValueMap body = new LinkedMultiValueMap();
//        body.add("grant_type","password");
//        body.add("username","itheima");
//        body.add("password","itheima");
//
//        MultiValueMap headers = new LinkedMultiValueMap();
//        body.add("Authorization",base64Encoder("changgou","changgou"));
//
//        HttpEntity<MultiValueMap<String,String>> requestEntity = new HttpEntity<>(body,headers);


        //指定service-id,eureka微服务中的id
        ServiceInstance serviceInstance = loadBalancerClient.choose("user-auth");
        //通过服务的实例可以获取路径
        //http://localhost:9200
        URI uri = serviceInstance.getUri();
        //拼接路径
        String url = uri + "/oauth/token";

        //body
        MultiValueMap<String,String> body = new LinkedMultiValueMap<String,String>();
        body.add("grant_type","password");//以密码模式申请令牌token
        body.add("username",username);//用户名
        body.add("password",password);//密码

        //header
        //封装HttpEntity,请求实体
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
        //客户端ID和客户端密匙
        headers.add("Authorization",base64Encoder(clientId,clientSecret));//value是经过base64编码的

        HttpEntity<MultiValueMap<String,String>> requestEntity = new HttpEntity<>(body,headers);

        //400或401不抛出异常
        restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){
            @Override
            public void handleError(ClientHttpResponse response) throws IOException {
                if(response.getRawStatusCode() != 400 && response.getRawStatusCode() != 401){
                    super.handleError(response);
                }
            }
        });

        //发送请求
        ResponseEntity<Map> exchange = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class);
        Map map = exchange.getBody();

        //创建封装实体类
        AuthToken authToken = new AuthToken();
        authToken.setAccessToken((String) map.get("access_token"));
        authToken.setJti((String) map.get("jti"));
        authToken.setRefreshToken((String) map.get("refresh_token"));

        //将令牌获取到了,并封装到实体类中.
        //将令牌存入到redis中,key是jti,value是token
        redisTemplate.boundValueOps(authToken.getJti()).set(authToken.getAccessToken(),ttl, TimeUnit.SECONDS);

        return authToken;
    }

    private String base64Encoder(String clientId, String clientSecret) {
        //字符串拼接
        String str = clientId + ":" + clientSecret;
        //base64编码
        byte[] encode = Base64Utils.encode(str.getBytes());
        System.out.println("encode : "+ new String(encode));
        return "Basic "+new String(encode);
    }
}
